package com.ubao.network;

import java.util.Vector;

import com.ubao.util.ScreenReceiver;


public class HttpHandler implements Timeable, Runnable {

	private boolean isRunning = false;

	// Http client
	private HttpClient httpClient = null;

	public HttpClient getHttpClient() {
		return httpClient;
	}

	// 超时时间
	private final int timeout;

	// 重新连接次数
	private final int retries;

	// HttpListener
	private HttpListener httpListener = null;

	// Http监视器
	private HttpMonitor monitor = null;

	// 等待发送的缓冲请求信息
	private Vector vctRequests = new Vector();

	private long lWaitTime = 0;

	private int state = STATE_REST;

	private final static int STATE_REST = 0;

	private final static int STATE_CANCEL = 1;

	private final static int STATE_ACTIVE = 2;

	public HttpHandler(HttpListener httpListener) {
		this(HttpConstants.DEFAULT_OVERTIME, HttpConstants.DEFAULT_RETRIES,
				httpListener);
	}

	public HttpHandler(HttpListener httpListener, int _msgId) {
		this(60, HttpConstants.DEFAULT_RETRIES,
				httpListener, _msgId);
	}

	public HttpHandler(int timeout, int retries, HttpListener httpListener) {
		this.retries = retries;
		this.timeout = timeout;
		this.httpListener = httpListener;
		this.isRunning = true;
		httpClient = new HttpClient();

		Thread t = new Thread(this);
		t.start();
	}

	public HttpHandler(int timeout, int retries, HttpListener httpListener,
			int _msgId) {
		this.retries = retries;
		this.timeout = timeout;
		this.httpListener = httpListener;
		this.isRunning = true;
		httpClient = new HttpClient(_msgId);

		Thread t = new Thread(this);
		t.start();
	}

	/**
	 * 设置监听器 (多用于屏幕切换后更改监听器用)
	 * 
	 * @param httpListener
	 */
	public void setHttpListener(HttpListener httpListener) {
		this.httpListener = httpListener;
	}

	public void run() {
		while (isRunning) {
			try {
				if (vctRequests.size() > 0) {
					lWaitTime = 0;
					RequestInterface request = null;
					synchronized (vctRequests) {
						if (vctRequests.size() > 0) {
							request = (RequestInterface) vctRequests
									.elementAt(0);
							vctRequests.removeElementAt(0);
						}
					}

					ResponseInterface resp = getResponse(request);

					// 数据到达 resp可能为null
					if (httpListener != null
							&& httpListener.acceptResponse(request)) {
						httpListener.completed(resp);
					}
					resp = null;
				}
				Thread.sleep(200);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	private void handleException(Exception ex) {
		if (httpListener != null && state == STATE_ACTIVE) {
			try {
				httpListener.exception(ex, this);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Provides an interrupt to the initiated request. This method is typically
	 */
	public void timeout() {// 数据接收超时
		cleanup();
		handleException(new Exception("网络连接超时..."));
	}

	/**
	 * 发送Request
	 * 
	 * @param request
	 */
	public void sendRequest(RequestInterface request) {
		sendRequest(request, false);
	}

	public void sendRequest(RequestInterface request,
			final boolean removeOldRequests) {
		if (request == null) {
			return;
		}
		synchronized (vctRequests) {
			if (removeOldRequests)
				vctRequests.removeAllElements();
			vctRequests.addElement(request);
		}
	}

	/**
	 * 接收数据
	 * 
	 * @return
	 * @throws Exception
	 */
	public ResponseInterface getResponse(RequestInterface request)
			throws Exception {
		ResponseInterface resp = null;

		int thisTry = 1;
		while (thisTry <= retries) {
			try {
				startTimer();
				state = STATE_ACTIVE;
				// 处理数据过程可能比较长 不建议放在synchronized域中
				resp = httpClient.getResponse(request);

				stopTimer();
				state = STATE_REST;

				break;
			} catch (Exception e) {
//				if (e.getMessage().equals(NewInfoResponse.NEW_INFO_EXCEPTION)) {
//					handleException(e);
//				}
				stopTimer();
				if (state == STATE_CANCEL) {
					state = STATE_REST;
					break;
				} else if (thisTry >= retries) {
					// 三次连接失败导致的通讯失败
					cleanup();
					if (httpListener != null
							&& httpListener.acceptResponse(request)) {
						handleException(new Exception("网络连接失败..."));
					}
				} else {
					if (ScreenReceiver.bScreenOf_NetOn) {
						try {
							Thread.sleep(1300);
						} catch (InterruptedException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
					} else {
						// break;
						thisTry = 14;
					}
				}
				state = STATE_REST;
			} finally {
				thisTry++;
			}
		}
		return resp;
	}

	/**
	 * 关闭连接,释放相关资源
	 */
	private void cleanup() {
		try {
			// 关闭监视器
			this.cancelTimer();
			monitor = null;

			// 回收http资源
			httpClient.cleanup();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void cleanUpHttpClient() {
		try {
			if (httpClient != null) {
				httpClient.cleanup();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取当前发送信息的条数
	 * 
	 * @return int
	 */
	public int getVctRequests() {
		synchronized (vctRequests) {
			return vctRequests.size();
		}
	}

	/**
	 * 中断线程
	 */
	public void stop() {
		// 请空缓存请求数据
		synchronized (vctRequests) {
			vctRequests.removeAllElements();
		}

		httpListener = null;
		cleanup();

		// 中断数据接收监听
		isRunning = false;
		httpClient = null;

	}

	public void cancelAccess() {
		if (state == STATE_ACTIVE) {
			state = STATE_CANCEL;
			cleanup();
		}
	}

	public void startTimer() {
		if (timeout > 0) {
			monitor = getRequestTimer();
			monitor.startTimer();
		}
	}

	private HttpMonitor getRequestTimer() {
		if (monitor == null) {
			monitor = new HttpMonitor(this, timeout);
			monitor.start();
		}
		return monitor;
	}

	/**
	 * Issues a stopTimer() call to the <code>SocketMonitor</code>.
	 * 
	 * @see java.io.InputStream
	 */
	public void stopTimer() {
		if (timeout > 0 && monitor != null) {
			monitor.stopTimer();
		}
	}

	/**
	 * Issues a cancelTimer() call to the <code>SocketMonitor</code>.
	 */
	public void cancelTimer() {
		if (timeout > 0) {
			if (monitor != null) {
				monitor.cancelTimer();
			}
		}
	}

	public void pauseTimer() {
		if (monitor != null) {
			monitor.pauseMonitor();
		}
	}

	public void resumeTimer() {
		if (monitor != null) {
			monitor.resumeMonitor();
		}
	}

}
